using System;
using System.Collections.Generic;
using MessagingWPF.Infrastructure.Utilities;

namespace MessagingWPF.Infrastructure
{
	/// <summary>
	/// A thread-safe subscription collection.
	/// </summary>
	public class SubscriptionRegistry : ISubscriptionRegistry
	{
		private readonly ListDictionary<Type, Subscription> _Subscriptions =
			new ListDictionary<Type, Subscription>();

		#region ISubscriptionRegistry Members

		/// <summary>
		/// Gets the subscriptions.
		/// </summary>
		/// <param name="messageType">Type of the message.</param>
		/// <returns>The list of subscriptions.</returns>
		public List<Subscription> GetSubscriptions(Type messageType)
		{
			Ensure.ArgumentIsNotNull(messageType, "messageType");

			lock (_Subscriptions)
			{
				return new List<Subscription>(_Subscriptions[messageType]);
			}
		}

		/// <summary>
		/// Adds the subscriptions.
		/// </summary>
		/// <param name="subscriptions">The subscriptions.</param>
		public void AddSubscriptions(IEnumerable<Subscription> subscriptions)
		{
			Ensure.ArgumentIsNotNull(subscriptions, "subscriptions");

			lock (_Subscriptions)
			{
				foreach (var subscription in subscriptions)
				{
					if (!_Subscriptions[subscription.MessageType].Contains(subscription))
					{
						_Subscriptions.Add(subscription.MessageType, subscription);
					}
				}
			}
		}

		/// <summary>
		/// Adds the subscription.
		/// </summary>
		/// <param name="subscription">The subscription.</param>
		public void AddSubscription(Subscription subscription)
		{
			Ensure.ArgumentIsNotNull(subscription, "subscription");

			AddSubscriptions(new[] {subscription});
		}

		/// <summary>
		/// Removes the subscriptions.
		/// </summary>
		/// <param name="subscriptions">The subscriptions.</param>
		public void RemoveSubscriptions(IEnumerable<Subscription> subscriptions)
		{
			Ensure.ArgumentIsNotNull(subscriptions, "subscriptions");

			lock (_Subscriptions)
			{
				foreach (var subscription in subscriptions)
				{
					_Subscriptions.Remove(subscription.MessageType, subscription);
				}
			}
		}

		/// <summary>
		/// Removes the subscription.
		/// </summary>
		/// <param name="subscription">The subscription.</param>
		public void RemoveSubscription(Subscription subscription)
		{
			Ensure.ArgumentIsNotNull(subscription, "subscription");

			RemoveSubscriptions(new[] {subscription});
		}

		#endregion
	}
}